//
//  DemoTimmer.m
//  ocdemo
//
//  Created by JIENING ZHANG on 2019/7/25.
//  Copyright © 2019 JIENING ZHANG. All rights reserved.
//

// https://www.jianshu.com/p/0c050af6c5ee

#import "DemoTimmer.h"
#import "LZKButtonAddition.h"

@interface DemoTimmer ()

@property (nonatomic, strong) NSTimer           *timer;
@property (nonatomic, strong) UIButton          *timerActionButton;

@property (nonatomic) dispatch_source_t         gcdTimer;
@property (nonatomic) BOOL                      gcdTimerRepeat;
@end

@implementation DemoTimmer

- (void)dealloc {
    NSLog(@"DemoTimmer dealloc");
    
    // 如果仅仅在 dealloc 中清除timer 是做不到的，因为 timer 和 vc 是处于相互引用的状态，不会被自动回收
    // so在vc的 viewWillDisappear 中清除timer，才能让vc在消失后被自动回收，执行到 dealloc
    // NSTimer的创建与撤销必须在同一个线程操作、performSelector的创建与撤销必须在同一个线程操作。
    if(_timer) {
        [_timer invalidate];
        _timer = nil;
    }
}

- (void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];
    
    // 如果仅仅在 dealloc 中清除timer 是做不到的，因为 timer 和 vc 是处于相互引用的状态，不会被自动回收
    // so在vc的 viewWillDisappear 中清除timer，才能让vc在消失后被自动回收，执行到 dealloc
    // NSTimer的创建与撤销必须在同一个线程操作、performSelector的创建与撤销必须在同一个线程操作。
    if(_timer) {
        [_timer invalidate];
        _timer = nil;
    }
    
    if(_gcdTimer) {
        dispatch_cancel(_gcdTimer);
    }
}

- (void)viewDidLoad {
    [super viewDidLoad];
    
    self.title = @"timer";
    self.view.backgroundColor = [UIColor whiteColor];
    
    //self.timer = [NSTimer timerWithTimeInterval:1.0 target:self selector:@selector(repeateTimerAction) userInfo:nil repeats:YES];
    
    _timerActionButton = [[UIButton alloc]initWithFrame:CGRectMake(30, 130, self.view.frame.size.width-60, 32)];
    _timerActionButton.layer.masksToBounds = YES;
    _timerActionButton.layer.cornerRadius = 8;
    _timerActionButton.titleForStateNormal=@"click to start timer";
    _timerActionButton.titleColorForStateNormal = [UIColor whiteColor];
    _timerActionButton.backgroundColorForStateNormal = [UIColor greenColor];
    [_timerActionButton addTarget:self action:@selector(onTimerActionButtonTouch:) forControlEvents:UIControlEventTouchUpInside];
    
    [self.view addSubview:_timerActionButton];
    
    
    UIButton *gcdTimerActionButton = [[UIButton alloc]initWithFrame:CGRectMake(30, 190, self.view.frame.size.width-60, 32)];
    gcdTimerActionButton.layer.masksToBounds = YES;
    gcdTimerActionButton.layer.cornerRadius = 8;
    gcdTimerActionButton.titleForStateNormal=@"click to start gcd timer";
    gcdTimerActionButton.titleColorForStateNormal = [UIColor whiteColor];
    gcdTimerActionButton.backgroundColorForStateNormal = [UIColor greenColor];
    [gcdTimerActionButton addTarget:self action:@selector(onGCDTimerActionButtonTouch:) forControlEvents:UIControlEventTouchUpInside];
    
    [self.view addSubview:gcdTimerActionButton];
    
    UIButton *gcdAfterActionButton = [[UIButton alloc]initWithFrame:CGRectMake(30, 250, self.view.frame.size.width-60, 32)];
    gcdAfterActionButton.layer.masksToBounds = YES;
    gcdAfterActionButton.layer.cornerRadius = 8;
    gcdAfterActionButton.titleForStateNormal=@"click to dispatch_after";
    gcdAfterActionButton.titleColorForStateNormal = [UIColor whiteColor];
    gcdAfterActionButton.backgroundColorForStateNormal = [UIColor greenColor];
    [gcdAfterActionButton addTarget:self action:@selector(onGCDAfterActionButtonTouch:) forControlEvents:UIControlEventTouchUpInside];
    
    [self.view addSubview:gcdAfterActionButton];
}

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];

    [self onTimerActionButtonTouch:nil];
}

- (void)onGCDTimerActionButtonTouch:(id)sender {
    
    UIButton *button = (UIButton *)sender;
    
    if(_gcdTimer && dispatch_testcancel(_gcdTimer) == 0){
        // 如果 _gcdTimer 存在且未被取消
        
        // gcd timer 取消
        dispatch_cancel(_gcdTimer);
    
        button.titleForStateNormal = @"gcd timmer cancel";
        return;
    }
    
    button.titleForStateNormal = [NSString stringWithFormat:@"gcd timer begin, %@", [NSDate date]];
    
    double delayInSeconds = 2.0;
    // 翻转 repeat
    _gcdTimerRepeat = !(_gcdTimerRepeat);
    
    // gcd timer 创建
    // 如此创建的gcd timer是repeat执行的
    self.gcdTimer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_main_queue());
    
    // gcd timer 时间设置
    dispatch_source_set_timer(_gcdTimer, DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC, 0);
    
    // gcd timer action设置
    __weak UIButton *weakButton = button;
    dispatch_source_t gcdTimer4Block = self.gcdTimer;
    BOOL repeat4Block = self.gcdTimerRepeat;
    
    dispatch_source_set_event_handler(_gcdTimer, ^{

        // 因为要操作ui，使用main_queue
        __strong UIButton *strongButton = weakButton;
        if(! weakButton) {
            NSLog(@"dispatch_source_set_event_handler block, fail to get strongButton");
            return;
        }
        
        strongButton.titleForStateNormal = [NSString stringWithFormat:@"gcd timer，%@, %@", (repeat4Block ? @"repeat" :@"once"), [NSDate date]];
        
        // 如果想一次性执行, 这里cancel
        if(! repeat4Block) {
            dispatch_cancel(gcdTimer4Block);
            return;
        }
    });
    
    // gcd timer 启动
    dispatch_resume(_gcdTimer);
}

- (void)onGCDAfterActionButtonTouch:(id)sender {
    
    UIButton *gcdAfterActionButton = (UIButton *)sender;
    
    gcdAfterActionButton.titleForStateNormal = @"dispatch_after call, begin";
    double delayInSeconds = 2.0;
    dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
    
    gcdAfterActionButton.enabled = NO;
    
    __weak UIButton *weakButton = gcdAfterActionButton;
    dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
        
        // 因为要操作ui，使用main_queue
        __strong UIButton *strongButton = weakButton;
        if(! weakButton) {
            NSLog(@"dispatch_after block, fail to get strongButton");
            return;
        }
        //执行事件
        strongButton.titleForStateNormal = [NSString stringWithFormat:@"dispatch_after block, %@", [NSDate date]];
        gcdAfterActionButton.enabled = YES;
    });

}

- (void)onTimerActionButtonTouch:(id)sender {
    if(_timer) {
        
        [_timer invalidate];
        _timer = nil;
        
        _timerActionButton.titleForStateNormal= @"nstimer stoped";
    } else {
        // 当前是主线程
        // NSTimer的创建与撤销必须在同一个线程操作、performSelector的创建与撤销必须在同一个线程操作。
        self.timer = [NSTimer timerWithTimeInterval:1.0 target:self selector:@selector(repeateTimerAction) userInfo:nil repeats:YES];
        [[NSRunLoop currentRunLoop]addTimer:self.timer  forMode:NSRunLoopCommonModes];
        
        _timerActionButton.titleForStateNormal = @"nstimer begin";
    }
}

- (void)repeateTimerAction {
    _timerActionButton.titleForStateNormal= [NSString stringWithFormat:@"nstimer running, %@", [NSDate date]];
}

@end
